import { KV } from "../addons/kv";

/**
 * 为了防止多客户端在没有同步时写入造成覆盖，需要设置一个写锁
 * 写锁 60 秒后生效
 */
interface ConfigLock {
  value: string;
  timestamp: number;
}

export type EnvValue = { type: "inherit" } | { type: "custom"; custom: string };
type Env = { key: string } & EnvValue;

interface Config {
  token: string;
  cloudflareId: string;
  default: {
    host: {
      ssh: { server: { allowedKeys: string[] } };
      envs: { key: string; value: string }[];
    };
  };
  scripts: { id: string; script: string }[];
  hosts: {
    id: string;
    token: string;
    name: string;
    restart: number;
    ssh: {
      publicKey: string;
      privateKey: string;
      server: { port: number; allowedKeys: string[]; enabled: boolean };
    };
    envs: Env[];
    crontabs: {
      id: string;
      cron: string;
      script: string;
      envs: Env[];
      enabled: boolean;
    }[];
  }[];
  forwards: {
    id: string;
    from: { host: string } & (
      | { type: "ssh" }
      | { type: "custom"; custom: { ip: string; port: number } }
    );
    to: { host: string; port: number };
  }[];
}

const CONFIG_LOCK_KEY = "config-lock";
const CONFIG_KEY = "config";
const DEFAULT_CONFIG_LOCK: ConfigLock = { value: "", timestamp: 0 };
const DEFAULT_CONFIG: Config = {
  token: "",
  cloudflareId: "",
  default: { host: { ssh: { server: { allowedKeys: [] } }, envs: [] } },
  scripts: [],
  hosts: [
    {
      id: "1",
      token: "1",
      name: "1",
      restart: 0,
      ssh: {
        privateKey: "",
        publicKey: "",
        server: { port: 0, allowedKeys: [], enabled: true },
      },
      envs: [],
      crontabs: [],
    },
    {
      id: "2",
      token: "2",
      name: "2",
      restart: 0,
      ssh: {
        privateKey: "",
        publicKey: "",
        server: { port: 0, allowedKeys: [], enabled: true },
      },
      envs: [],
      crontabs: [],
    },
    {
      id: "3",
      token: "3",
      name: "3",
      restart: 0,
      ssh: {
        privateKey: "",
        publicKey: "",
        server: { port: 0, allowedKeys: [], enabled: true },
      },
      envs: [],
      crontabs: [],
    },
  ],
  forwards: [],
};

const cache: { configLock?: ConfigLock; config?: Config } = {};

export async function getConfigLock(kv: KV) {
  cache.configLock ??=
    (await kv.get<ConfigLock>(CONFIG_LOCK_KEY)) ?? DEFAULT_CONFIG_LOCK;
  return cache.configLock;
}

export async function putConfigLock(kv: KV, value: string) {
  const timestamp = Date.now() + 60000;
  await kv.put(CONFIG_LOCK_KEY, { value, timestamp });
  return timestamp;
}

export async function getConfig(kv: KV) {
  cache.config ??= (await kv.get<Config>(CONFIG_KEY)) ?? DEFAULT_CONFIG;
  return cache.config;
}

export async function putConfig(kv: KV, value: Config) {
  await kv.put(CONFIG_KEY, value);
  cache.config = value;
}
